package com.test.mytest.javacv.face;

import static org.bytedeco.javacpp.opencv_core.CV_32SC1;
import static org.bytedeco.javacpp.opencv_face.createFisherFaceRecognizer;
import static org.bytedeco.javacpp.opencv_imgcodecs.CV_LOAD_IMAGE_GRAYSCALE;
import static org.bytedeco.javacpp.opencv_imgcodecs.imread;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.IntBuffer;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.bytedeco.javacpp.DoublePointer;
import org.bytedeco.javacpp.IntPointer;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacpp.opencv_core.MatVector;
import org.bytedeco.javacpp.opencv_face.FaceRecognizer;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;

import com.test.mytest.javacv.JavacvService;
import com.test.mytest.javacv.samples.OpenCVFaceRecognizer;

public class FaceRecognizerService {
	
	
	private static final String DEFAULT_DIR = System.getProperty("user.dir")+"\\image\\javacv\\face";
	private FaceRecognizer faceRecognizer;
	private String name;
	private double confidence;
    private String names[];
	private String dir=DEFAULT_DIR;
	Java2DFrameConverter java2dFrameConverter=new Java2DFrameConverter();
	OpenCVFrameConverter.ToMat toMat=new OpenCVFrameConverter.ToMat();

	public static void main(String[] args) {
    	//头像训练数据
        String registeredFaceDir = System.getProperty("user.dir")+"\\image\\javacv\\face\\";
        String testImagePath = registeredFaceDir+"hjx3.jpg";//要识别的头像
		Mat testImage = imread(testImagePath, CV_LOAD_IMAGE_GRAYSCALE);
        
		FaceRecognizerService r=new FaceRecognizerService();
        r.init();
        r.predict(testImage);
        
    }
    
	public void init(){
		File root = new File(dir);

        FilenameFilter imgFilter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                name = name.toLowerCase();
                return name.endsWith(".jpg") || name.endsWith(".pgm") || name.endsWith(".png");
            }
        };
        System.out.println("dir===="+dir);
        File[] imageFiles = root.listFiles(imgFilter);
        init(Arrays.asList(imageFiles));
	}
	
    public void init(List<File> list){
    	int length = list.size();
    	names=new String[length];
    	Mat[] listMat=new Mat[list.size()];
        int counter = 0;

        for (File image : list) {
            Mat img = imread(image.getAbsolutePath(), CV_LOAD_IMAGE_GRAYSCALE);
            String name = image.getName();
            System.out.println(name+"=="+name.lastIndexOf("."));
            name=name.substring(0, name.lastIndexOf("."));
			names[counter]=name;
			listMat[counter]=img;
            counter++;
        }
        init(names, listMat);
    }
    public void init(String[] names,Mat...mats){
    	int length = names.length;
    	MatVector images = new MatVector(length);
    	this.names=names;
        Mat labels = new Mat(length, 1, CV_32SC1);
        IntBuffer labelsBuf = labels.createBuffer();

        int counter = 0;

        for (Mat img : mats) {
            images.put(counter, img);

            labelsBuf.put(counter, counter);

            counter++;
        }
        faceRecognizer = createFisherFaceRecognizer();
        // faceRecognizer = createEigenFaceRecognizer();
        // faceRecognizer = createLBPHFaceRecognizer();

        faceRecognizer.train(images, labels);
    }
    
    public  void predict(Mat mat){
    	IntPointer label = new IntPointer(1);
        DoublePointer confidence = new DoublePointer(1);
        faceRecognizer.predict(mat, label, confidence);
        int predictedLabel = label.get(0);
        if (predictedLabel>=0&&predictedLabel<names.length) {
        	name=names[predictedLabel];
		}else{
			name=null;
		}
        this.confidence=confidence.get();//值越小，表示相似度越高。
//        System.out.println("name:"+name+"===Predicted label: " + predictedLabel+"===confidence:"+confidence.get());
    }

	public String getName() {
		return name;
	}

	public double getConfidence() {
		return confidence;
	}

	public String getDir() {
		return dir;
	}

	public void setDir(String dir) {
		this.dir = dir;
	}
	public double getMatchRatio(){
		double d=confidence;
		int i = JavacvService.FACE_WIDTH*JavacvService.FACE_HEIGHT;
		d=i-d;
		d=d*100;
		d=d/i;
		return d;
	}

	public void predict(BufferedImage faceImage) {
		try {
			
			String path=new File(dir).getParent()+"\\now.jpg";
			JavacvService.saveImage(faceImage, path);
			predict(imread(path, CV_LOAD_IMAGE_GRAYSCALE));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
